package com.unibeta.cloudtest.mesher.auth.interceptor;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.unibeta.cloudtest.config.ConfigurationProxy;
import com.unibeta.cloudtest.mesher.auth.annotation.Authorization;
import com.unibeta.cloudtest.mesher.auth.context.AuthContext;
import com.unibeta.cloudtest.mesher.auth.context.AuthContextHolder;
import com.unibeta.cloudtest.mesher.auth.exception.AuthException;
import com.unibeta.cloudtest.mesher.service.UpmService;

import cn.hutool.jwt.JWT;

@Configuration
public class AuthenticationInterceptor implements HandlerInterceptor {

//	@Autowired
//	RedisRepository redis;
	
	@Autowired
	UpmService upmService;

	@Override
	public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
			Object object) throws Exception {

//		if (!com.unibeta.cloudtest.mesher.config.Configuration.isAuthorizationEnabled()) {
//			return true;
//		}

		if (!(object instanceof HandlerMethod)) {
			return true;
		}

		HandlerMethod handlerMethod = (HandlerMethod) object;
		Method method = handlerMethod.getMethod();
		Class clazz = handlerMethod.getBeanType();

		Authorization methodAntuorized = method.getAnnotation(Authorization.class);
		Authorization classAntuorized = (Authorization) clazz.getAnnotation(Authorization.class);

		if ((classAntuorized != null && classAntuorized.required())
				|| (null != methodAntuorized && methodAntuorized.required())) {

			String authToken = httpServletRequest.getHeader(Authorization.NAME);
			String token = httpServletRequest.getHeader(Authorization.TOKEN);

			if (authToken != null) {
				String[] tk = authToken.split(Authorization.BEARER);
				if (tk.length == 2 && !StringUtils.isEmpty(tk[1])) {
					token = tk[1];
				}

				if (!StringUtils.isEmpty(token)) {
					AuthContext authContext = new AuthContext();

					JWT jwt = JWT.of(token);

					int exp = Integer.valueOf(jwt.getPayload(JWT.EXPIRES_AT).toString());
					if (new Date(exp).after(new Date())) {
						throw new AuthException("auth_error_001", "accessing is dennied, token had been expired.");
					}

					Object auds = jwt.getPayload(JWT.AUDIENCE);
					if (auds instanceof List) {
						List l = (List) auds;
						String username = l.get(0).toString();
						authContext.getCurrentUserDetails().setUsername(username);
						authContext.getCurrentUserDetails().setDetails(upmService.getUserByName(username));
						AuthContextHolder.setContext(authContext);

						ConfigurationProxy.setCLOUDTEST_HOME(new File(com.unibeta.cloudtest.mesher.config.ConfigurationProxy.getWorkspace() + "/"
								+ AuthContextHolder.getContext().getCurrentUserDetails().getUsername() + "-default/").getCanonicalPath());
						
					} else {
						throw new AuthException("auth_error_000", "accessing is dennied, please login first.");
					}

				} else {
					throw new AuthException("auth_error_000", "token is required.");
				}
			} else {
				throw new AuthException("auth_error_000", "token is required.");
			}
		}
		

		return true;
	}
}
